<template>
  <div id="test" class="test-view">
    <div class="main-map">
      <Map ref="mapRef" @map-loaded="onMapLoaded" @full-screen="handleFullScreen('test')" />
    </div>
    <div class="mini-map">
      <MiniMap ref="miniMapRef" />
    </div>
  </div>
</template>

<script setup>
import { ref, onBeforeUnmount } from "vue";
import * as Cesium from "cesium";
import CreateFrustum from "@/utils/frustumUtils";
import eventBus from "@/utils/other/eventBus";

const mapRef = ref(null);
const miniMapRef = ref(null);

let cesiumTools = null;
let viewer = null;

let movableEntity = null;
let modelPosition = null;
let movableHeading = 90; // 朝向，单位：度
let movablePitch = 90;
let movableFov = 20;
let movableDistance = 500;

// 增加键盘事件监听
const handleKeyDown = e => {
  if (!movableEntity) return;
  const moveStep = 0.00003;
  const headingStep = 0.6;
  const heightStep = 3;

  const heading = movableHeading - 90;
  // 取当前目标位置的经纬高
  let carto = Cesium.Cartographic.fromCartesian(modelPosition);
  let lon = Cesium.Math.toDegrees(carto.longitude);
  let lat = Cesium.Math.toDegrees(carto.latitude);
  let height = carto.height;
  switch (e.key.toLowerCase()) {
    case "w":
      lat += moveStep * Math.cos(Cesium.Math.toRadians(heading));
      lon += moveStep * Math.sin(Cesium.Math.toRadians(heading));
      break;
    case "s":
      lat -= moveStep * Math.cos(Cesium.Math.toRadians(heading));
      lon -= moveStep * Math.sin(Cesium.Math.toRadians(heading));
      break;
    case "a":
      lat += moveStep * Math.cos(Cesium.Math.toRadians(heading - 90));
      lon += moveStep * Math.sin(Cesium.Math.toRadians(heading - 90));
      break;
    case "d":
      lat += moveStep * Math.cos(Cesium.Math.toRadians(heading + 90));
      lon += moveStep * Math.sin(Cesium.Math.toRadians(heading + 90));
      break;
    case "q":
      movableHeading = movableHeading - headingStep;
      break;
    case "e":
      movableHeading = movableHeading + headingStep;
      break;
    case "c":
      height += heightStep;
      break;
    case "z":
      height = Math.max(0, height - heightStep);
      break;
    default:
      return;
  }
  // 设置新目标
  modelPosition = Cesium.Cartesian3.fromDegrees(lon, lat, height);
  syncFrustum();
  cameraFollow();
};

/**
 * 视角跟随
 */
const cameraFollow = () => {
  const cameraPosition = viewer.camera.positionWC;
  const distance = Cesium.Cartesian3.distance(cameraPosition, modelPosition);
  if (distance != 1000) {
    viewer.camera.lookAt(
      modelPosition,
      new Cesium.HeadingPitchRange(
        Cesium.Math.toRadians(0),
        Cesium.Math.toRadians(-45),
        1500
      )
    );
    // 解除lookAt锁定
    viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
  }
};

/**
 * 视椎体与无人机同步
 */
const syncFrustum = (isSync = true) => {
  // 计算 orientation
  const frustumOrientation = Cesium.Transforms.headingPitchRollQuaternion(
    modelPosition,
    new Cesium.HeadingPitchRoll(
      Cesium.Math.toRadians(movableHeading),
      Cesium.Math.toRadians(movablePitch),
      0
    )
  );
  // 添加视锥体
  CreateFrustum.getInstance(viewer, {
    position: modelPosition,
    orientation: frustumOrientation,
    fov: movableFov,
    far: movableDistance
  });

  if (isSync) {
    // 广播无人机空间状态，供miniMap联动
    eventBus.emit("uav-camera-sync", {
      position: modelPosition,
      heading: movableHeading,
      pitch: movablePitch,
      distance: movableDistance,
      fov: movableFov // 视场角：视椎体开口角度
    });
  }
};

/**
 * 添加模型、视锥体和辅助线
 */
const addModel = () => {
  // 添加模型实体
  movableEntity = viewer.entities.add({
    position: new Cesium.CallbackProperty(() => modelPosition, false),
    orientation: new Cesium.CallbackProperty(() => {
      return Cesium.Transforms.headingPitchRollQuaternion(
        modelPosition,
        // +90是为了使得模型默认朝向正北方向
        new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(movableHeading), 0, 0)
      );
    }, false),
    model: {
      uri: "models/arrow.gltf",
      // 关键设置：强制固定大小
      minimumPixelSize: 100, // 最小像素大小
      maximumPixelSize: 100, // 最大像素大小(设为相同值实现固定大小)
      scale: 0.005, // 基础缩放比例
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 500000), // 可见距离范围
      // 浅色设置 - 使用柔和的浅蓝色
      color: Cesium.Color.LIGHTSKYBLUE, // 半透明浅天蓝色
      colorBlendMode: Cesium.ColorBlendMode.MIX,
      colorBlendAmount: 0.1 // 增加混合比例使颜色更柔和
    }
  });
};

const handleClick = (entity, position, flag) => {
  if (movableEntity) return;

  modelPosition = Cesium.Cartesian3.fromDegrees(
    Number(position.longitude),
    Number(position.latitude),
    Number(300)
  );

  // 自动调整相机视角
  cameraFollow();

  // 添加视锥体
  syncFrustum();

  // 添加模型
  addModel();
  const positionCallback = () => {
    return modelPosition;
  };
  // 添加模型到地面的黄色辅助线
  cesiumTools.addGroundLine(positionCallback);
};

// 地图加载完成的回调
const onMapLoaded = (tools, cesiumViewer) => {
  try {
    cesiumTools = tools;
    viewer = cesiumViewer;

    // 组件挂载时监听键盘
    window.addEventListener("keydown", handleKeyDown);

    tools.addClickEvent(handleClick);

    // 监听miniMap相机变化，联动无人机朝向和俯仰
    eventBus.on("miniMap-camera-change", ({ heading, pitch, fov }) => {
      movableHeading = heading;
      movablePitch = pitch;
      movableFov = fov;
      syncFrustum(false);
    });
  } catch (error) {
    console.error("Error in onMapLoaded:", error);
  }
};

// 添加全屏处理方法
const handleFullScreen = id => {
  cesiumTools.divFullScreen(id);
};

// 组件销毁时清理资源
onBeforeUnmount(() => {
  cesiumTools.destroy();
  window.removeEventListener("keydown", handleKeyDown);
  CreateFrustum.destroyInstance();
});
</script>

<style scoped lang="scss">
.test-view {
  display: flex;
  width: 100vw;
  height: 100vh;
}
.main-map {
  width: 70%;
  height: 100%;
}
.mini-map {
  border-left: 4px solid #999;
  width: 30%;
  height: 100%;
}
</style>